﻿using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json.Serialization;
using Sharp.Portal.AdminLTE.FormField;
using Sharp.Portal.Interface;
using Sharp.Portal.Mvc.Form;
using Sharp.Portal.Mvc.Models;

namespace Sharp.Portal.AdminLTE.Provider
{
    /// <summary>
    /// AdminLTE Form
    /// </summary>
    public class FromPage : ITemplateProvider
    {
        private static readonly CamelCasePropertyNamesContractResolver Cpncr = new CamelCasePropertyNamesContractResolver();
        /// <summary>
        /// 获取模板
        /// </summary>
        /// <param name="model"></param>
        /// <param name="isMobileDevice"></param>
        /// <returns></returns>
        public string GetTemplate(object model, bool isMobileDevice)
        {
            StringBuilder sb = new StringBuilder();
            Rendering(sb, model);
            return sb.ToString();
        }
        #region 渲染界面

        /// <summary>
        /// 渲染界面
        /// </summary>
        /// <param name="sb"></param>
        /// <param name="model"></param>
        private void Rendering(StringBuilder sb, object model)
        {
            sb.AppendFormat("@model {0}\r\n", model.GetType().FullName);

            var form = (model as ISharpForm).UI as BSSharpFrom;
            form.InitComplete();

            if (form.OpenWith == OpenWith.Window || form.OpenWith == OpenWith.Window2Column)
            {
                #region 窗口布局
                sb.AppendLine("<div class=\"modal\">");
                if (form.LargeSize)
                {
                    sb.AppendLine("<div class=\"modal-dialog lg\">");
                }
                else
                {
                    sb.AppendFormat("\r\n<div class=\"modal-dialog\">");
                }

                //sb.AppendLine("<div class=\"modal-content animated flipInY\">");
                sb.AppendLine("<div class=\"modal-content\">");
                sb.AppendLine("<div class=\"modal-header\">");
                sb.AppendLine("<button type=\"button\" class=\"close\" data-dismiss=\"modal\">");
                sb.Append("<span aria-hidden=\"true\"> &times; </span>");
                sb.AppendLine("<span class=\"sr-only\"> 关闭 </span></button>");
                if (model is BaseViewModel)
                {
                    sb.AppendLine("<h4 class=\"modal-title\"> @Model.PageTitle </h4>");
                }
                else
                {
                    sb.AppendFormat("<h4 class=\"modal-title\"> @Model.UI.Title </h4>");
                }
                sb.AppendLine("</div>");

                sb.AppendLine("<div class=\"modal-body\" id=\"modalcontent\">");

                if (form.Sections.Any(s => s.Fields.Any(f => f.DataType == DataType.Upload)))
                {
                    sb.AppendLine("@using(Html.Bootstrap().BeginForm(c => c.Horizontal().Enctype().FormData()))");
                }
                else
                {
                    sb.AppendLine("@using(Html.Bootstrap().BeginForm(c => c.Horizontal()))");
                }


                sb.AppendLine("{");

                if (form.Sections.Count == 1)
                {
                    RendingEditing(sb, form);
                }
                else
                {
                    TabRendingEditing(sb, form);
                }

                sb.AppendLine("}");
                sb.AppendLine("</div>");

                sb.AppendLine("<div class=\"modal-footer\">");
                sb.AppendLine("<div class=\"btn-group\">");
                sb.AppendFormat(
                    "@Html.Bootstrap().LinkButton(\"保存\", ToolBarIco.Save).Style(BootstrapStyle.Primary).Click(\"window.app.saveForm(event,'\" + @Url.Action(\"{0}\") + \"');\").Attribute(\"data-search\", HttpContext.Current.Request.QueryString[\"ListControlId\"]).Hide(Model.UI.CheckReadOnlyForm())\r\n", form.PostAction);


                sb.AppendLine(
                    "@Html.Bootstrap().LinkButton(\"关闭\", ToolBarIco.Close).Style(BootstrapStyle.Default).Attribute(\"data-dismiss\", \"modal\")");
                sb.AppendLine("</div>");
                sb.AppendLine("</div>");

                sb.AppendLine("</div>");
                sb.AppendLine("</div>");
                sb.AppendLine("</div>");
                #endregion
            }
            else if (form.OpenWith == OpenWith.Tile || form.OpenWith == OpenWith.Tile2Column)
            {
                #region 平铺布局
                if (form.Layout != null)
                {
                    sb.AppendLine("@{");
                    sb.AppendFormat("Layout = \"{0}\";", form.Layout.LayoutPath);
                }
                else
                {
                    sb.AppendLine("@if (ViewBag.IsPjaxRequest == false)");
                    sb.AppendLine("{");
                    sb.AppendLine("Layout = \"~/Areas/Platform/Views/Shared/__Layout.cshtml\";");
                }
                sb.AppendLine("}");

                if (form.Layout != null)
                {
                    sb.AppendFormat("@section {0}{{ ", form.Layout.SectionName);
                }

                sb.AppendLine("<section class=\"content-header\">");
                sb.AppendFormat("<h1>{0}</h1>", form.Title);

                sb.AppendLine("</section>");
                sb.AppendLine("<section class=\"content\">");

                sb.AppendLine("<div class=\"box box-primary\">");
                sb.AppendLine("<div class=\"box-body\" id=\"modalcontent\">");

                sb.AppendLine("<div class=\"row\">");
                sb.AppendLine("<div class=\"col-md-12\">");
                sb.AppendLine("@using(Html.Bootstrap().BeginForm(c => c.Horizontal()))");
                sb.AppendLine("{");

                if (form.Sections.Count == 1)
                {
                    RendingEditing(sb, form);
                }
                else
                {
                    TabRendingEditing(sb, form);
                }

                sb.AppendLine("}");
                sb.AppendLine("</div>");

                sb.AppendLine("<div class=\"box-footer text-center box-outfooter\">");
                sb.AppendFormat("@Html.Bootstrap().LinkButton(\"保存\", ToolBarIco.Save).Style(BootstrapStyle.Primary).Click(\"window.app.saveForm(event,'\" + Url.Action(\"{0}\") + \"');\").Hide(Model.UI.CheckReadOnlyForm())\r\n", form.PostAction);
                sb.AppendFormat("@Html.Bootstrap().LinkButton(\"返回\", ToolBarIco.Back).Style(BootstrapStyle.Default).Click(\"window.app.loadUI('\" + Url.Action(\"{0}\") + \"');\")\r\n", form.GoBackAction);
                sb.AppendLine("</div>");

                sb.AppendLine("</div>");
                sb.AppendLine("</div>");
                sb.AppendLine("</div>");
                sb.AppendLine("</section>");

                if (form.Layout != null)
                {
                    sb.AppendLine("}");
                }
                #endregion
            }
        }

        private void RendingEditing(StringBuilder sb, SharpFrom uI)
        {
            sb.AppendLine("@:<div class=\"row\">");
            RendingEditing(sb, uI, uI.Sections[0]);
            sb.AppendLine("@:</div>");
        }

        private void RendingEditing(StringBuilder sb, SharpFrom form, FormSection formSection)
        {
            var fields = formSection.Fields;
            bool fieldInserted = false;
            foreach (var field in fields.Where(x => x.FieldType == FieldType.HiddenInput))
            {
                sb.AppendFormat("@Html.HiddenFor(x => x.{0})\r\n", field.Name);
            }
            foreach (var field in fields.Where(x => x.FieldType != FieldType.HiddenInput))
            {
                if (field.HideField) continue;

                sb.AppendFormat("if (this.CheckFieldPermission(\"{0}\")) \r\n{{\r\n", Cpncr.GetResolvedPropertyName(field.Name));

                if (form.OpenWith == OpenWith.Window2Column || form.OpenWith == OpenWith.Tile2Column)
                {
                    sb.AppendLine("<div class=\"col-md-6\">");
                }
                if (form.OpenWith == OpenWith.Window || form.OpenWith == OpenWith.Tile)
                {
                    sb.AppendLine("<div class=\"col-md-12\">");
                }
                if (field.FieldType == FieldType.TextBox)
                {
                    if (field.DataType == DataType.Html)
                    {
                        sb.AppendLine("<div class=\"form-group\">");
                        sb.Append("\r\n@Html.LabelFor(m => m." + field.Name +
                                  ", new { @class = \"col-md-3 col-sm-5 control-label\" })");
                        sb.AppendLine("<div class=\"col-md-9 col-sm-7\">");
                        sb.Append(new HtmlEditorField(field.Name).Build());
                        sb.AppendLine("</div>");
                        sb.AppendLine("</div>");
                    }
                    else if (field.DataType == DataType.MultilineText)
                    {
                        sb.AppendLine("<div class=\"form-group\">");
                        sb.AppendFormat("@Html.LabelFor(m => m.{0}, new {{ @class = \"col-md-3 col-sm-5 control-label\" }})", field.Name);
                        sb.AppendLine("<div class=\"col-md-9 col-sm-7\">");
                        sb.Append(new TextAreaField(field.Name).Build());
                        sb.AppendLine("</div>");
                        sb.AppendLine("</div>");
                    }
                    else
                    {
                        sb.AppendLine("<div class=\"form-group\">");
                        sb.AppendFormat("@Html.LabelFor(m => m.{0}, new {{ @class = \"col-md-3 col-sm-5 control-label\" }})", field.Name);
                        sb.AppendLine("<div class=\"col-md-9 col-sm-7\">");

                        switch (field.DataType)
                        {
                            case DataType.Date:
                            case DataType.DateTime:
                            case DataType.Time:
                                sb.Append(new DateField(field.Name).Build());
                                break;
                            case DataType.Password:
                            case DataType.EmailAddress:
                                sb.Append(new TextField(field.Name, field.DataType).Build());
                                break;
                            case DataType.ImageUrl:
                                sb.Append(new ImageField(field.Name).Build());
                                break;
                            case DataType.Upload:
                                sb.Append(new ImageUploadField(field.Name).Build());
                                break;
                            default:
                                if (field.PropertyType == typeof(int))
                                {
                                    sb.Append(new NumberField(field.Name).Build());
                                }
                                else
                                {
                                    sb.Append(new TextField(field.Name).Build());
                                }
                                break;
                        }
                        sb.AppendLine("</div>");
                        sb.AppendLine("</div>");
                    }
                }
                else if (field.FieldType == FieldType.Upload)
                {
                    //sb.AppendFormat("x.FileUploadField().DataIndex(\"{0}\").Text(\"{1}\").ColumnWidth(1).Padding(4),", property.Name, "");
                }
                else if (field.FieldType == FieldType.OrgTreeList || field.FieldType == FieldType.TreeList)
                {
                    sb.AppendLine("<div class=\"form-group\">");
                    sb.AppendFormat("@Html.LabelFor(m => m.{0}, new {{ @class = \"col-md-3 col-sm-5 control-label\" }})\r\n<div class=\"col-md-9 col-sm-7\"> ", field.Name);
                    sb.AppendFormat(new TreeListField(field.Name, field.DataSourceName, field.DisplayField, field.ValueField).Build());
                    sb.AppendLine("</div></div>");
                }

                else if (field.FieldType == FieldType.MasterData)
                {
                    sb.AppendLine("<div class=\"form-group\">");
                    sb.AppendFormat("@Html.LabelFor(m => m.{0}, new {{ @class = \"col-md-3 col-sm-5 control-label\" }})", field.Name);
                    sb.AppendLine("<div class=\"col-md-9 col-sm-7\" style=\"line-height:34px;\">");
                    sb.Append(new MasterDataField(field.Name, field.MasterDataCategory).Build());
                    sb.AppendLine("</div>");
                    sb.AppendLine("</div>");

                }
                else if (field.FieldType == FieldType.Boolean)
                {
                    sb.AppendLine("<div class=\"form-group\">");
                    sb.AppendFormat("@Html.LabelFor(m => m.{0}, new {{ @class = \"col-md-3 col-sm-5 control-label\" }})", field.Name);
                    sb.AppendLine("<div class=\"col-md-8 col-sm-7 col-md-offset-1\"><div class=\"checkbox\">");
                    sb.Append(new CheckboxField(field.Name).Build());
                    sb.AppendLine("</div></div>");
                    sb.AppendLine("</div>");
                }
                else if (field.FieldType == FieldType.DropDownList)
                {
                    sb.AppendLine("<div class=\"form-group\">");
                    sb.AppendFormat("@Html.LabelFor(m => m.{0}, new {{ @class = \"col-md-3 col-sm-5 control-label\" }})", field.Name);
                    sb.AppendLine("<div class=\"col-md-9 col-sm-7\">");

                    sb.AppendLine(new DropDownListField(field.Name, field.DataSourceName, field.DisplayField, field.ValueField).Build());
                    sb.AppendLine("</div>");
                    sb.AppendLine("</div>");
                }
                else if (field.FieldType == FieldType.SelectBox)
                {
                    sb.AppendLine("<div class=\"form-group\">");
                    sb.AppendFormat("@Html.LabelFor(m => m.{0}, new {{ @class = \"col-md-3 col-sm-5 control-label\" }})\r\n<div class=\"col-md-9 col-sm-7\"> ", field.Name);
                    sb.AppendLine(new SelectBoxField(field.Name, field.DataSourceName, field.DisplayField, field.ValueField).Build());
                    sb.AppendLine("</div>");
                    sb.AppendLine("</div>");
                }
                else
                {
                    sb.AppendLine("<div class=\"form-group\">");
                    sb.AppendFormat(
                        "@Html.LabelFor(m => m.{0}, new {{ @class = \"col-md-3 col-sm-5 control-label\" }})",
                        field.Name);
                    sb.AppendLine("<div class=\"col-md-9 col-sm-7\">");
                    sb.AppendFormat("@Html.Bootstrap().TextBoxFor(m => m.{0})", field.Name);
                    sb.AppendFormat("@Html.ValidationMessageFor(m => m.{0})", field.Name);
                    sb.AppendLine("</div>");
                    sb.AppendLine("</div>");
                }

                fieldInserted = true;


                sb.AppendLine("</div>");

                sb.AppendLine("}");
            }

            if (fieldInserted)
            {
                sb.Remove(sb.Length - 1, 1);
            }
            sb.AppendLine();
        }

        private void TabRendingEditing(StringBuilder sb, SharpFrom form)
        {
            sb.AppendLine("@:<div class=\"clearfix\">");
            sb.AppendLine("@:<ul class=\"nav nav-tabs\">");
            for (var i = 0; i < form.Sections.Count; i++)
            {
                sb.AppendFormat("@:<li class=\"{2}\"><a href=\"#tab{0}\" data-toggle=\"tab\">{1}</a></li>\r\n", i, form.Sections[i].Title, i == 0 ? "active" : "");

            }
            sb.AppendLine("@:</ul>");
            sb.AppendLine("@:<div class=\"tab-content\">");
            for (var i = 0; i < form.Sections.Count; i++)
            {
                sb.AppendFormat("@:<div class=\"tab-pane fade {1}\" id=\"tab{0}\">\r\n", i, i == 0 ? " in active" : "");
                RendingEditing(sb, form, form.Sections[i]);
                sb.AppendLine("@:</div>");
            }

            sb.AppendLine("@:</div>");
            sb.AppendLine("@:</div>");
        }
        #endregion
    }
}
